package cn.fintecher.pangolin.service.business.web;

import cn.fintecher.pangolin.common.enums.BaseSelect;
import cn.fintecher.pangolin.common.enums.ManagementType;
import cn.fintecher.pangolin.common.model.DepartmentModel;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.Constants;
import cn.fintecher.pangolin.common.web.BaseController;
import cn.fintecher.pangolin.entity.mysql.CaseInfo;
import cn.fintecher.pangolin.entity.mysql.QCaseInfo;
import cn.fintecher.pangolin.service.business.model.request.*;
import cn.fintecher.pangolin.service.business.model.response.*;
import cn.fintecher.pangolin.service.business.repository.jparepository.CaseInfoRepository;
import cn.fintecher.pangolin.service.business.service.BaseService;
import cn.fintecher.pangolin.service.business.service.CaseInfoService;
import com.querydsl.core.BooleanBuilder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author wangxiangdong
 * @Description 案件相关查询
 * @Date 2019/8/30 16:24
 **/
@RestController
@RequestMapping("/api/caseInfoController")
@Api(value = "案件相关查询", description = "案件相关查询")
public class CaseInfoController extends BaseController {

    @Autowired
    private CaseInfoRepository caseInfoRepository;

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private BaseService baseService;

    @Autowired
    private CaseInfoService caseInfoService;

    @GetMapping("/queryOrganizationDistributeCases")
    @ApiOperation(value = "查询部门待分配案件", notes = "查询部门待分配案件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query", value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<DistributedCaseResponse>> queryOrganizationDistributeCases(Pageable pageable, OrganizationDistributeCaseRequest request, @RequestHeader(value = "X-UserToken") String token) {
        BooleanBuilder booleanBuilder = request.generateQueryBuilder();
        UserModel userModel = baseService.getUserByToken(token);
        DepartmentModel departmentModel = baseService.getDepartmentByToken(token);
        if (Objects.equals(userModel.getIsManage().name(), ManagementType.YES.name())) {
            booleanBuilder.and(QCaseInfo.caseInfo.department.departCode.like(StringUtils.join(departmentModel.getDepartCode(), "%")));
        } else {
            booleanBuilder.and(QCaseInfo.caseInfo.department.departCode.eq(departmentModel.getDepartCode()));
        }
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            booleanBuilder.and(QCaseInfo.caseInfo.principalId.in(userModel.getPrincipalIds()));
        }
        Sort sort = new Sort(Sort.Direction.ASC, "delegationDate").and(new Sort(Sort.Direction.ASC, "operatorTime"));
        pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        Page<CaseInfo> caseInfoPage = caseInfoRepository.findAll(booleanBuilder, pageable);
        Page<DistributedCaseResponse> distributedCaseResponses = caseInfoPage.map(x -> modelMapper.map(x, DistributedCaseResponse.class));
        return new ResponseEntity<>(distributedCaseResponses, HttpStatus.OK);
    }

    @GetMapping("/queryPersonalCases")
    @ApiOperation(value = "查询个人已分配案件", notes = "查询个人已分配案件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query", value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<DistributedCaseResponse>> queryPersonalCases(Pageable pageable, PersonalDistributedRequest request, @RequestHeader(value = "X-UserToken") String token) {
        BooleanBuilder booleanBuilder = request.generateQueryBuilder();
        UserModel userModel = baseService.getUserByToken(token);
        DepartmentModel departmentModel = baseService.getDepartmentByToken(token);
        if (Objects.equals(userModel.getIsManage().name(), ManagementType.YES.name())) {
            booleanBuilder.and(QCaseInfo.caseInfo.currentCollector.department.departCode.like(StringUtils.join(departmentModel.getDepartCode(), "%")));
        } else {
            booleanBuilder.and(QCaseInfo.caseInfo.currentCollector.id.eq(userModel.getId()));
        }
        Page<CaseInfo> caseInfoPage = caseInfoRepository.findAll(booleanBuilder, pageable);
        Page<DistributedCaseResponse> distributedCaseResponses = caseInfoPage.map(x -> modelMapper.map(x, DistributedCaseResponse.class));
        return new ResponseEntity<>(distributedCaseResponses, HttpStatus.OK);
    }

    @GetMapping("/queryStopCases")
    @ApiOperation(value = "查询停催案件", notes = "查询停催案件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query", value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<StopCasesResponse>> queryStopCases(Pageable pageable, StopCasesRequest request, @RequestHeader(value = "X-UserToken") String token) {
        BooleanBuilder booleanBuilder = request.generateQueryBuilder();
        UserModel userModel = baseService.getUserByToken(token);
        DepartmentModel departmentModel = baseService.getDepartmentByToken(token);
        if (Objects.equals(userModel.getIsManage(), BaseSelect.YES)) {
            booleanBuilder.and(QCaseInfo.caseInfo.currentCollector.department.departCode.like(StringUtils.join(departmentModel.getDepartCode(), "%")));
        } else {
            booleanBuilder.and(QCaseInfo.caseInfo.currentCollector.id.eq(userModel.getId()));
        }
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            booleanBuilder.and(QCaseInfo.caseInfo.principalId.in(userModel.getPrincipalIds()));
        }
        Sort sort = new Sort(Sort.Direction.DESC, "stopTime");
        pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        Page<CaseInfo> caseInfoPage = caseInfoRepository.findAll(booleanBuilder, pageable);
        return new ResponseEntity<>(caseInfoPage.map(x -> modelMapper.map(x, StopCasesResponse.class)), HttpStatus.OK);
    }

    @GetMapping("/queryCollectingCases")
    @ApiOperation(value = "查询在催案件", notes = "查询在催案件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query", value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<CollectingCasesResponse>> queryCollectingCases(Pageable pageable, CollectingCasesRequest request, @RequestHeader(value = "X-UserToken") String token) {
        BooleanBuilder booleanBuilder = request.generateQueryBuilder();
        UserModel userModel = baseService.getUserByToken(token);
        DepartmentModel departmentModel = baseService.getDepartmentByToken(token);
        if (Objects.equals(userModel.getIsManage(), BaseSelect.YES)) {
            booleanBuilder.and(QCaseInfo.caseInfo.currentCollector.department.departCode.like(StringUtils.join(departmentModel.getDepartCode(), "%")));
        } else {
            booleanBuilder.and(QCaseInfo.caseInfo.currentCollector.id.eq(userModel.getId()));
        }
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            booleanBuilder.and(QCaseInfo.caseInfo.principalId.in(userModel.getPrincipalIds()));
        }
        Sort sort = new Sort(Sort.Direction.ASC, "delegationDate")
                .and(new Sort(Sort.Direction.ASC, "followTime"))
                .and(new Sort(Sort.Direction.DESC, "overdueAmtTotal"));
        pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        Page<CaseInfo> caseInfoPage = caseInfoRepository.findAll(booleanBuilder, pageable);
        return new ResponseEntity<>(caseInfoPage.map(x -> modelMapper.map(x, CollectingCasesResponse.class)), HttpStatus.OK);
    }

    @GetMapping("/querySettleCases")
    @ApiOperation(value = "查询结清案件", notes = "查询结清案件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query", value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<CollectingCasesResponse>> querySettleCases(Pageable pageable, SettleCasesRequest request, @RequestHeader(value = "X-UserToken") String token) {
        BooleanBuilder booleanBuilder = request.generateQueryBuilder();
        UserModel userModel = baseService.getUserByToken(token);
        DepartmentModel departmentModel = baseService.getDepartmentByToken(token);
//        if (Objects.equals(userModel.getIsManage(), BaseSelect.YES)) {
//            BooleanBuilder builder = new BooleanBuilder();
//            builder.and(QCaseInfo.caseInfo.currentCollector.department.departCode.like(departmentModel.getDepartCode() + "%")
//                    .or(QCaseInfo.caseInfo.department.departCode.like(departmentModel.getDepartCode() + "%")));
//            booleanBuilder.and(builder);
//        } else {
//            booleanBuilder.and(QCaseInfo.caseInfo.currentCollector.id.eq(userModel.getId()));
//        }
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            booleanBuilder.and(QCaseInfo.caseInfo.principalId.in(userModel.getPrincipalIds()));
        }
        Page<CaseInfo> caseInfoPage = caseInfoRepository.findAll(booleanBuilder, pageable);
        Page<CollectingCasesResponse> page = caseInfoPage.map(x -> modelMapper.map(x, CollectingCasesResponse.class));
        page.getContent().forEach(e -> e.setDepartmentName(Objects.nonNull(e.getName1()) ? e.getName1() : e.getName2()));
        return new ResponseEntity<>(page, HttpStatus.OK);
    }


    @GetMapping("/queryPublicCases")
    @ApiOperation(value = "公共案件查询", notes = "公共案件查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query", value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<DistributedCaseResponse>> queryPublicCases(Pageable pageable, PublicCasesRequest request, @RequestHeader(value = "X-UserToken") String token) {
        UserModel userModel = baseService.getUserByToken(token);
        BooleanBuilder booleanBuilder = request.generateQueryBuilder();
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            booleanBuilder.and(QCaseInfo.caseInfo.principalId.in(userModel.getPrincipalIds()));
        }
        Sort sort = new Sort(Sort.Direction.ASC, "delegationDate", "operatorTime");
        pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        Page<CaseInfo> caseInfoPage = caseInfoRepository.findAll(booleanBuilder, pageable);
        Page<DistributedCaseResponse> distributedCaseResponsePage = caseInfoPage.map(x -> modelMapper.map(x, DistributedCaseResponse.class));
        return new ResponseEntity<>(distributedCaseResponsePage, HttpStatus.OK);
    }

    @PostMapping("/stopCases")
    @ApiOperation(value = "停催", notes = "停催")
    public ResponseEntity<Void> stopCases(@RequestBody IdsRequest idsRequest, @RequestHeader(value = "X-UserToken") String token) {
        baseService.getUserByToken(token);
        caseInfoService.stopCase(idsRequest.getIds());
        return ResponseEntity.ok().build();
    }

    @PostMapping("/changeCaseType")
    @ApiOperation(value = "更改案件类型", notes = "更改案件类型")
    public ResponseEntity<Void> changeCaseType(@RequestBody ChangeCaseTypeRequest changeCaseTypeRequest, @RequestHeader(value = "X-UserToken") String token) {
        UserModel userModel = baseService.getUserByToken(token);
        caseInfoService.changeCaseType(changeCaseTypeRequest, userModel);
        return ResponseEntity.ok().build();
    }

    /**
     * 检查案件是否存在协催申请和协催案件
     */
    @PostMapping("/checkCase")
    @ApiOperation(value = "检查案件是否存在协催申请和协催案件", notes = "检查案件是否存在协催申请和协催案件")
    public ResponseEntity<CheckCaseResponse> checkCase(@RequestBody ChangeCaseTypeRequest request) {
        log.info("REST request to check case,{}", request);
        CheckCaseResponse response = caseInfoService.checkCase(request);
        return ResponseEntity.ok().body(response);
    }

    @PostMapping("/backCollectCasePool")
    @ApiOperation(value = "复催", notes = "复催")
    public ResponseEntity<Void> backCollectCasePool(@RequestBody IdsRequest idsRequest, @RequestHeader(value = "X-UserToken") String token) {
        baseService.getUserByToken(token);
        caseInfoService.backCollectCasePool(idsRequest.getIds());
        return ResponseEntity.ok().build();
    }

    @PostMapping("/changeRetireCases")
    @ApiOperation(value = "立即转退案", notes = "立即转退案")
    public ResponseEntity<Void> changeRetireCases(@RequestBody CaseReturnRequest caseReturnRequest, @RequestHeader(value = "X-UserToken") String token) {
        UserModel userByToken = baseService.getUserByToken(token);
        caseInfoService.changeRetireCases(caseReturnRequest, userByToken);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/getBatchNumber")
    @ApiOperation(value = "查询案件池批次号", notes = "查询案件池批次号")
    public ResponseEntity<List<String>> getBatchNumber(@RequestHeader(value = "X-UserToken") String token, String poolName) {
        UserModel userModel = baseService.getUserByToken(token);
        List<String> batchNumberList = caseInfoService.getBatchNumber(poolName, userModel);
        return ResponseEntity.ok().body(batchNumberList);
    }

    @PostMapping("/updateCaseEndDate")
    @ApiOperation(value = "刷新退案时间", notes = "刷新退案时间")
    public ResponseEntity<Void> updateCaseEndDate(@RequestBody UpdateCaseEndDateRequest updateCaseEndDateRequest, @RequestHeader(value = "X-UserToken") String token) {
        UserModel userByToken = baseService.getUserByToken(token);
        caseInfoService.updateCaseEndDate(updateCaseEndDateRequest, userByToken);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/getPersonalById")
    @ApiOperation(value = "通过id查询person信息", notes = "通过id查询person信息")
    public ResponseEntity<PersonalResponse> getPersonalById(@RequestParam String personalId) {
        return ResponseEntity.ok().body(caseInfoService.getPersonalById(personalId));
    }

    @PostMapping("/getPrintMessage")
    @ApiOperation(value = "通过id查询案件信息", notes = "通过id查询案件信息")
    public ResponseEntity<List<CasePrintMessageResponse>> getPrintMessage(@RequestBody PrintMessageRequest printMessageRequest) {
        List<CaseInfo> caseInfoList = caseInfoRepository.findAllById(printMessageRequest.getCaseIds());
        List<CasePrintMessageResponse> casePrintMessageResponse = caseInfoList.stream().map(caseInfo -> modelMapper.map(caseInfo, CasePrintMessageResponse.class)).collect(Collectors.toList());
        return ResponseEntity.ok().body(casePrintMessageResponse);
    }

    @PostMapping("/updateCaseMessage")
    @ApiOperation(value = "更新案件信息", notes = "更新案件信息")
    public ResponseEntity<Void> updateCaseMessage(@RequestBody CaseUpdateMessageRequest caseUpdateMessageRequest) {
        caseInfoService.updateCaseMessage(caseUpdateMessageRequest);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/caseCollectionStatus")
    @ApiOperation(value = "催收执行页快捷菜单案件列表", notes = "催收执行页快捷菜单案件列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query",
                    value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query",
                    value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
                    value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<CaseInfoStatusResponse>> caseCollectionStatus(CaseCollectionStatusRequest caseCollectionStatusRequest, @RequestHeader(value = "X-UserToken") String token, Pageable pageable) {
        Page<CaseInfoStatusResponse> page = caseInfoService.caseCollectionStatus(caseCollectionStatusRequest, token, pageable);
        return new ResponseEntity<>(page, HttpStatus.OK);
    }

    @PostMapping("/searchDebtBatch")
    @ApiOperation(value = "根据客户信息查询共债案件批次", notes = "根据客户信息查询共债案件批次")
    public ResponseEntity searchDebtBatch(@RequestBody CollectionDebtRequest request,
                                          @RequestHeader(value = "X-UserToken") String token, Pageable pageable) {
        DebtInfoResponse response = new DebtInfoResponse();
        caseInfoService.searchDebtBatchNumber(request, response, token);
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    @GetMapping("/searchDebtCardInfo")
    @ApiOperation(value = "根据客户信息查询共债案件卡号", notes = "根据客户信息查询共债案件卡号")
    public ResponseEntity searchDebtCardInfo(CollectionDebtRequest request) {
        List<AccountInfoResponse> accountInfoResponseList = caseInfoService.searchDebtCardInfo(request);
        return new ResponseEntity<>(accountInfoResponseList, HttpStatus.OK);
    }

    @GetMapping("/searchDebtCaseCount")
    @ApiOperation(value = "根据客户信息查询公债案件的数量", notes = "根据客户信息查询公债案件的数量")
    public ResponseEntity searchDebtCaseCount(CollectionDebtRequest request, @RequestHeader(value = "X-UserToken") String token) {
        Map<String, Long> baseMap = caseInfoService.searchDebtCaseCount(Constants.BASE_CASE, request, token);
        Map<String, Long> hisMap = caseInfoService.searchDebtCaseCount(Constants.HISTORY_CASES, request, token);
        baseMap.put("samePrincipal", baseMap.get("samePrincipal") + hisMap.get("samePrincipal"));
        baseMap.put("differentPrincipal", baseMap.get("differentPrincipal") + hisMap.get("differentPrincipal"));
        return new ResponseEntity<>(baseMap, HttpStatus.OK);
    }

    /**
     * 流转待分配查询
     */
    @ApiOperation(value = "流转待分配查询", notes = "流转待分配查询")
    @GetMapping("/getAllCirculationCase")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query",
                    value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query",
                    value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
                    value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<DistributedCaseResponse>> getAllCirculationCase(Pageable pageable, CirculationCaseRequest request,
                                                                               @RequestHeader(value = "X-UserToken") String token) {
        log.info("REST request to get all circulation case,{}", request);
        Page<DistributedCaseResponse> page = caseInfoService.getAllCirculationCase(request, pageable, token);
        return ResponseEntity.ok().body(page);
    }
}
